package com.example.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 安全告警服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SecurityAlertService {

    private final RedisTemplate<String, Object> redisTemplate;

    @Value("${security.alert.enabled:true}")
    private boolean alertEnabled;

    @Value("${security.alert.email.enabled:false}")
    private boolean emailAlertEnabled;

    @Value("${security.alert.sms.enabled:false}")
    private boolean smsAlertEnabled;

    /**
     * 发送安全告警
     */
    @Async
    public void sendSecurityAlert(SecurityAlertType alertType, String title, String message, 
                                 Map<String, Object> details) {
        if (!alertEnabled) {
            return;
        }

        try {
            // 创建告警记录
            SecurityAlert alert = createAlert(alertType, title, message, details);
            
            // 存储告警
            storeAlert(alert);
            
            // 检查是否需要发送通知
            if (shouldSendNotification(alertType)) {
                sendNotification(alert);
            }
            
            log.warn("安全告警: type={}, title={}, message={}", alertType, title, message);
            
        } catch (Exception e) {
            log.error("发送安全告警异常: {}", e.getMessage(), e);
        }
    }

    /**
     * 创建告警记录
     */
    private SecurityAlert createAlert(SecurityAlertType alertType, String title, String message, 
                                    Map<String, Object> details) {
        SecurityAlert alert = new SecurityAlert();
        alert.setId(generateAlertId());
        alert.setType(alertType);
        alert.setTitle(title);
        alert.setMessage(message);
        alert.setDetails(details);
        alert.setTimestamp(LocalDateTime.now());
        alert.setSeverity(determineSeverity(alertType));
        alert.setStatus(AlertStatus.NEW);
        
        return alert;
    }

    /**
     * 存储告警
     */
    private void storeAlert(SecurityAlert alert) {
        try {
            String alertKey = "security_alert:" + alert.getId();
            redisTemplate.opsForValue().set(alertKey, alert, 30, TimeUnit.DAYS);
            
            // 添加到告警列表
            String listKey = "security_alerts:" + alert.getType().name();
            redisTemplate.opsForList().leftPush(listKey, alert.getId());
            redisTemplate.expire(listKey, 30, TimeUnit.DAYS);
            
            // 更新统计
            updateAlertStatistics(alert);
            
        } catch (Exception e) {
            log.error("存储告警异常: {}", e.getMessage(), e);
        }
    }

    /**
     * 更新告警统计
     */
    private void updateAlertStatistics(SecurityAlert alert) {
        try {
            String statsKey = "alert_stats:" + LocalDateTime.now().toLocalDate();
            redisTemplate.opsForHash().increment(statsKey, "total", 1);
            redisTemplate.opsForHash().increment(statsKey, alert.getType().name(), 1);
            redisTemplate.opsForHash().increment(statsKey, alert.getSeverity().name(), 1);
            redisTemplate.expire(statsKey, 90, TimeUnit.DAYS);
        } catch (Exception e) {
            log.debug("更新告警统计异常: {}", e.getMessage());
        }
    }

    /**
     * 检查是否需要发送通知
     */
    private boolean shouldSendNotification(SecurityAlertType alertType) {
        // 检查告警频率限制
        String rateLimitKey = "alert_rate_limit:" + alertType.name();
        Long count = redisTemplate.opsForValue().increment(rateLimitKey);
        redisTemplate.expire(rateLimitKey, 3600, TimeUnit.SECONDS);
        
        // 每小时最多发送10次同类型告警
        if (count > 10) {
            return false;
        }
        
        // 高危告警总是发送
        return alertType.getSeverity() == AlertSeverity.CRITICAL || 
               alertType.getSeverity() == AlertSeverity.HIGH;
    }

    /**
     * 发送通知
     */
    private void sendNotification(SecurityAlert alert) {
        try {
            if (emailAlertEnabled) {
                sendEmailNotification(alert);
            }
            
            if (smsAlertEnabled && alert.getSeverity() == AlertSeverity.CRITICAL) {
                sendSmsNotification(alert);
            }
            
            // 发送到监控系统
            sendToMonitoringSystem(alert);
            
        } catch (Exception e) {
            log.error("发送通知异常: {}", e.getMessage(), e);
        }
    }

    /**
     * 发送邮件通知
     */
    private void sendEmailNotification(SecurityAlert alert) {
        // 实际实现中应该集成邮件服务
        log.info("发送邮件告警: {}", alert.getTitle());
    }

    /**
     * 发送短信通知
     */
    private void sendSmsNotification(SecurityAlert alert) {
        // 实际实现中应该集成短信服务
        log.info("发送短信告警: {}", alert.getTitle());
    }

    /**
     * 发送到监控系统
     */
    private void sendToMonitoringSystem(SecurityAlert alert) {
        // 实际实现中应该集成监控系统（如Prometheus、Grafana等）
        log.info("发送到监控系统: {}", alert.getTitle());
    }

    /**
     * 确定告警严重程度
     */
    private AlertSeverity determineSeverity(SecurityAlertType alertType) {
        return alertType.getSeverity();
    }

    /**
     * 生成告警ID
     */
    private String generateAlertId() {
        return "ALERT_" + System.currentTimeMillis() + "_" + 
               String.format("%04d", (int)(Math.random() * 10000));
    }

    /**
     * 获取告警列表
     */
    public List<SecurityAlert> getAlerts(SecurityAlertType type, int limit) {
        try {
            String listKey = "security_alerts:" + type.name();
            List<Object> alertIds = redisTemplate.opsForList().range(listKey, 0, limit - 1);
            
            return alertIds.stream()
                    .map(id -> (SecurityAlert) redisTemplate.opsForValue().get("security_alert:" + id))
                    .filter(alert -> alert != null)
                    .toList();
                    
        } catch (Exception e) {
            log.error("获取告警列表异常: {}", e.getMessage(), e);
            return List.of();
        }
    }

    /**
     * 获取告警统计
     */
    public Map<String, Object> getAlertStatistics() {
        try {
            Map<String, Object> stats = new HashMap<>();
            String statsKey = "alert_stats:" + LocalDateTime.now().toLocalDate();
            
            Map<Object, Object> dailyStats = redisTemplate.opsForHash().entries(statsKey);
            stats.put("today", dailyStats);
            
            // 获取各类型告警数量
            Map<String, Long> typeStats = new HashMap<>();
            for (SecurityAlertType type : SecurityAlertType.values()) {
                String listKey = "security_alerts:" + type.name();
                Long count = redisTemplate.opsForList().size(listKey);
                typeStats.put(type.name(), count);
            }
            stats.put("byType", typeStats);
            
            return stats;
            
        } catch (Exception e) {
            log.error("获取告警统计异常: {}", e.getMessage(), e);
            return new HashMap<>();
        }
    }

    /**
     * 安全告警类型
     */
    public enum SecurityAlertType {
        DDOS_ATTACK(AlertSeverity.HIGH),
        SQL_INJECTION(AlertSeverity.CRITICAL),
        XSS_ATTACK(AlertSeverity.HIGH),
        COMMAND_INJECTION(AlertSeverity.CRITICAL),
        SESSION_HIJACKING(AlertSeverity.HIGH),
        BRUTE_FORCE_ATTACK(AlertSeverity.MEDIUM),
        API_ABUSE(AlertSeverity.MEDIUM),
        PAYMENT_FRAUD(AlertSeverity.CRITICAL),
        UNAUTHORIZED_ACCESS(AlertSeverity.HIGH),
        DATA_BREACH(AlertSeverity.CRITICAL),
        MALWARE_DETECTED(AlertSeverity.CRITICAL),
        SUSPICIOUS_ACTIVITY(AlertSeverity.MEDIUM),
        RATE_LIMIT_EXCEEDED(AlertSeverity.LOW),
        AUTHENTICATION_FAILURE(AlertSeverity.MEDIUM),
        PRIVILEGE_ESCALATION(AlertSeverity.HIGH);

        private final AlertSeverity severity;

        SecurityAlertType(AlertSeverity severity) {
            this.severity = severity;
        }

        public AlertSeverity getSeverity() {
            return severity;
        }
    }

    /**
     * 告警严重程度
     */
    public enum AlertSeverity {
        LOW, MEDIUM, HIGH, CRITICAL
    }

    /**
     * 告警状态
     */
    public enum AlertStatus {
        NEW, ACKNOWLEDGED, INVESTIGATING, RESOLVED, CLOSED
    }

    /**
     * 安全告警实体
     */
    public static class SecurityAlert {
        private String id;
        private SecurityAlertType type;
        private String title;
        private String message;
        private Map<String, Object> details;
        private LocalDateTime timestamp;
        private AlertSeverity severity;
        private AlertStatus status;

        // Getters and Setters
        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        
        public SecurityAlertType getType() { return type; }
        public void setType(SecurityAlertType type) { this.type = type; }
        
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        
        public Map<String, Object> getDetails() { return details; }
        public void setDetails(Map<String, Object> details) { this.details = details; }
        
        public LocalDateTime getTimestamp() { return timestamp; }
        public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; }
        
        public AlertSeverity getSeverity() { return severity; }
        public void setSeverity(AlertSeverity severity) { this.severity = severity; }
        
        public AlertStatus getStatus() { return status; }
        public void setStatus(AlertStatus status) { this.status = status; }
    }
}
